<template xmlns="http://www.w3.org/1999/html">
  <div v-title>
    <div id="map-container">
    </div>
    <div>
      <el-input v-model="searchMarkerText" class="searchSuggestInput" placeholder="请输入手机号"
                clearable
      ></el-input>
      <div class="rightPanelStyle">
        <el-table :data="paginatedList" border
                  @row-click="selectOneUser"
                  @sort-change="handleSort"
                  class="listTableStyle"
                  :max-height="tableMaxHeight"
        >
          <el-table-column label="手机号" min-width="120" show-overflow-tooltip fixed="left">
            <template slot-scope="scope">
              <el-popover trigger="hover" placement="top-start">
                <div style="width: 300px">
                  <el-descriptions :column="1">
                    <el-descriptions-item label="手机号">{{ scope.row.account }}</el-descriptions-item>
                    <el-descriptions-item label="昵称">{{ scope.row.nickName }}</el-descriptions-item>
                    <el-descriptions-item label="所属组织">{{ scope.row.deptName }}</el-descriptions-item>
                  </el-descriptions>
                </div>
                <span slot="reference">
                  {{ scope.row.account }}
                </span>
              </el-popover>
            </template>
          </el-table-column>
          <el-table-column label="上报时间" align="center" width="120px" sortable="custom" prop="latestTime">
            <template slot-scope="scope">
              <span>{{ scope.row.latestTime }}</span>
            </template>
          </el-table-column>
        </el-table>
        <el-pagination
          v-show="fetchPositionListSize>0"
          :total="fetchPositionListSize"
          layout="total,prev,next,jumper"
          :page.sync="queryParams.pageNum"
          :limit.sync="queryParams.pageSize"
          @current-change="handleCurrentPageChange"
        />
      </div>
    </div>
  </div>
</template>
<script>
import { listUserPosition } from '@/api/system/user'
import { parseTimeSearch, parseTimeMy } from '@/utils/ruoyi'

export default {
  name: 'mapContent',
  data() {
    return {
      // 所有用户的位置信息
      allUserPositionList: [],
      locationMap: null,
      center: [],
      cluster: null,
      markers: [],
      timer: '',
      searchMarkerText: '',
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        orderByAccount: undefined,
        orderByLatestTime: undefined
      },
      //选中的marker的手机号
      selectedAccount: 0,
      tableMaxHeight: window.innerHeight * 0.7
    }
  },
  computed: {
    /**
     * 过滤后的用户列表(未分页), 按用户名和手机号查询, 按上报时间排序
     */
    fetchPositionList() {
      let fetchList = []
      // 对allUserPositionList进行深克隆
      for (let i = 0, len = this.allUserPositionList.length; i < len; i++) {
        fetchList.push({ ...this.allUserPositionList[i] })
      }

      // 按手机号排序
      if (this.queryParams.orderByAccount) {
        if (this.queryParams.orderByAccount === 'asc') {
          fetchList.sort((a, b) => {
            return a.account - b.account
          })
        } else {
          fetchList.sort((a, b) => {
            return b.account - a.account
          })
        }
      }

      // 按上报时间排序
      if (this.queryParams.orderByLatestTime) {
        if (this.queryParams.orderByLatestTime === 'asc') {
          fetchList.sort((a, b) => {
            let aLatestTime = new Date(a.latestTime)
            let bLatestTime = new Date(b.latestTime)
            return aLatestTime - bLatestTime
          })
        } else {
          fetchList.sort((a, b) => {
            let aLatestTime = new Date(a.latestTime)
            let bLatestTime = new Date(b.latestTime)
            return bLatestTime - aLatestTime
          })
        }
      }

      // 按手机号或用户名进行过滤==过滤
      return fetchList.filter(item => {
        item.latestTime = parseTimeSearch(item.latestTime)
        return item.account.indexOf(this.searchMarkerText) !== -1 || item.nickName.indexOf(this.searchMarkerText) !== -1
      })
    },
    /**
     * 过滤后列表项的数量
     */
    fetchPositionListSize() {
      return this.fetchPositionList.length
    },
    /**
     * 分页后的列表数据
     */
    paginatedList() {
      let startIndex = (this.queryParams.pageNum - 1) * this.queryParams.pageSize
      let endIndex = (this.queryParams.pageNum) * this.queryParams.pageSize
      return this.fetchPositionList.filter((item, index) => {
        console.log(item)
        return index >= startIndex && index < endIndex
      })
    }
  },
  created() {
    this.initMap()
  },
  mounted() {
    // 浏览器页面大小发送变化时修改table的max-height
    window.onresize = () => {
      return (() => {
        this.tableMaxHeight = window.innerHeight * 0.7
      })()
    }
  },
  beforeDestroy() {
    clearInterval(this.timer)
  },
  methods: {
    /**
     * 给地图添加当前位置的标记, 工具条, 比例尺, 方向盘
     */
    addInitComponent(vueInstance) {
      // 给当前位置添加标记
      let currentLocationMarker = new AMap.Marker({
        position: [vueInstance.center[0], vueInstance.center[1]],
        // map: vueInstance.locationMap, //不显示
        label: {
          offset: new AMap.Pixel(0, 25),
          content: '<div>当前位置</div>',
          direction: 'center'
        }
      })

      // 加载工具条, 比例尺, 方向盘
      AMap.plugin(['AMap.ToolBar', 'AMap.Scale', 'AMap.ControlBar'], function() {
        let toolbar = new AMap.ToolBar()
        let scale = new AMap.Scale()

        vueInstance.locationMap.addControl(toolbar)
        vueInstance.locationMap.addControl(scale)
      })
    },
    /** 初始化地图, 创建并挂载, 添加当前位置的标记  */
    initMap() {
      let self = this
      AMap.plugin('AMap.Geolocation', function() {
        let geolocation = new AMap.Geolocation({
          // 是否使用高精度定位，默认：true
          enableHighAccuracy: true,
          // 设置定位超时时间，默认：无穷大
          timeout: 5000
        })

        geolocation.getCurrentPosition()
        AMap.event.addListener(geolocation, 'complete', onComplete)
        AMap.event.addListener(geolocation, 'error', onError)

        // 定位查询成功回调, data是具体的定位信息
        function onComplete(data) {
          // 挂在地图到容器, 中心点为查询的地址（web端根据ip查询）
          self.locationMap = new AMap.Map('map-container', {
            resizeEnable: true, //是否监控地图容器尺寸变化
            zoom: 7, //初始化地图层级, 默认省级
            center: [data.position.lng, data.position.lat] //初始化地图中心点
          })
          self.center = [data.position.lng, data.position.lat]
          self.addInitComponent(self)
          console.log(`设置定时器`)
          self.createMarkerCluster()
          self.timer = setInterval(self.createMarkerCluster, 30000)
        }

        // 定位出错
        function onError(data) {
          console.log('定位出错了!!')
          self.locationMap = new AMap.Map('map-container', {
            resizeEnable: true, //是否监控地图容器尺寸变化
            zoom: 7, //初始化地图层级
            center: [120.028666000000000, 30.241042000000000] //初始化地图中心点
          })
          self.center = [120.028666000000000, 30.241042000000000]
          self.addInitComponent(self)
          console.log(`设置定时器`)
          self.createMarkerCluster()
          self.timer = setInterval(self.createMarkerCluster, 30000)
        }
      })
    },
    /**
     * 渲染markers, 根据this.allUserPositionList中的数据生成marker进行添加
     * 标记设置鼠标移入、移出的时间, 使用点聚合
     */
    createMarkerCluster() {
      listUserPosition({ pageNum: 1 }).then(response => {
        this.allUserPositionList = response.rows
        // 渲染markers
        // 遍历allUserPositionList, 每次生成一个marker
        if (this.locationMap) {

          let markers = []
          let self = this
          console.log(`渲染markers, ${this.allUserPositionList.length}, zoom: ${this.locationMap.getZoom()}`)
          for (let value of this.allUserPositionList) {
            let infoWindowContent = []
            infoWindowContent.push(`<div style="background-color: white; width: 100%">`)
            infoWindowContent.push(`<div class="infoWindow-Title">${value.position}</div>`)
            infoWindowContent.push(`<div class="link-top"></div>`)
            // markerContent.push(`<img src="${value.imgUrl}" width="100px" height="100px"/> <br/>`)
            infoWindowContent.push(`<div class="infoWindow-Content">【昵称】${value.nickName}</div>`)
            infoWindowContent.push(`<div class="infoWindow-Content">【手机号】${value.account}</div>`)
            infoWindowContent.push(`<div class="infoWindow-Content2">【上报时间】${parseTimeMy(value.latestTime)}</div>`)
            infoWindowContent.push(`</div>`)

            let markerLabelContent = `<div class="markerLabelTextContainer">${value.nickName}</div>`
            let markerContent = `<div class="custom-content-marker"><img src="${value.imgUrl}" alt=""/></div>`

            // 设置显示顺序
            let zIndex = value.account === this.selectedAccount ? 1 : -1

            // 生成marker
            let marker = new AMap.Marker({
              position: [value.longitude, value.latitude],
              label: {
                content: markerLabelContent,
                offset: new AMap.Pixel(0, 21),
                direction: 'center'
              },
              content: markerContent,
              extData: { id: value.account },
              zIndex: zIndex
            })

            markers.push(marker)

            // marker添加鼠标移入事件, 显示信息窗体
            AMap.event.addListener(marker, 'mouseover', function() {
              let infoWindow = new AMap.InfoWindow({
                isCustom: true,
                content: infoWindowContent.join(''),
                offset: new AMap.Pixel(16, -50)
              })

              infoWindow.open(self.locationMap, marker.getPosition())
            })

            // marker添加鼠标移出事件, 清楚信息窗体
            AMap.event.addListener(marker, 'mouseout', function() {
              self.locationMap.clearInfoWindow()
            })
          }

          this.markers = markers
          this.locationMap.clearInfoWindow()
          // 点聚合
          if (this.cluster) {
            //非第一次渲染
            this.cluster.setMarkers(markers)
          } else {
            //第一次渲染
            this.cluster = new AMap.MarkerClusterer(this.locationMap, this.markers, {
              gridSize: 80,
              maxZoom: 11 //点聚合等级为市
            })
          }

          //使用高德地图插件方式创建点聚合
          // this.locationMap.plugin(['AMap.MarkerClusterer'], function() {
          //   new AMap.MarkerClusterer(self.locationMap, markers, { gridSize: 80 })
          // })
        }
      })
    },
    /**
     * 当鼠标点击一个列表项
     * @param event
     */
    selectOneUser(event) {
      // 获取点击列表项的手机号, 经度, 纬度
      let selectedAccount = event.account
      // 当前选中的手机号
      this.selectedAccount = selectedAccount
      let selectedLongitude = event.longitude
      let selectedLatitude = event.latitude
      // 设置地图中心点, 并将地图等级设置为18
      this.locationMap.setCenter([selectedLongitude, selectedLatitude])
      this.locationMap.setZoom(18)

      // 遍历markers, 将所有marker的zIndex设置为-1, 并获取选中的marker
      let selectedMarker
      for (let i = 0, len = this.markers.length; i < len; i++) {
        this.markers[i].setzIndex(-1)

        if (this.markers[i].getExtData().id === selectedAccount) {
          selectedMarker = this.markers[i]
        }
      }

      // 将选中的marker的zIndex设置为1, 设置下落动画, 重新渲染点聚合
      if (selectedMarker) {
        this.cluster.setMarkers(this.markers)
        selectedMarker.setzIndex(1)
        selectedMarker.setAnimation('AMAP_ANIMATION_DROP')
      }
    },
    /**
     * 点击排序按钮
     * @param event
     */
    handleSort(event) {
      // 转换排序的字符串, 将其转为sql中的形式
      let orderType = null
      if (event.order) {
        orderType = event.order === 'ascending' ? 'asc' : 'desc'
      }

      //先清空之前的排序
      this.queryParams.orderByAccount = undefined
      this.queryParams.orderByLatestTime = undefined

      // 设置查询参数中相应的排序标识字段
      if (event.prop === 'account') {
        this.queryParams.orderByAccount = orderType
      }
      if (event.prop === 'latestTime') {
        this.queryParams.orderByLatestTime = orderType
      }
    },
    /**
     * 修改分页的页面, prev, next, jumper都会调用该函数
     * @param currentPage 跳转后的页码
     */
    handleCurrentPageChange(currentPage) {
      this.queryParams.pageNum = currentPage
    }
  }
}
</script>

<style scoped>
#map-container {
  /*margin: 10px 10px;*/
  width: calc(80vw);
  height: calc(100vh);
  float: left;
}

.searchSuggestInput {
  width: 18%;
  margin-top: 2vh;
  margin-left: 1vw;
}

.rightPanelStyle {
  float: left;
  width: 18%;
  margin-top: calc(1vh);
  margin-left: calc(1vw);
}
</style>
